import MIPS.*;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Stack;

public class AnalyseMips {
    private ArrayList<Quaternion> IRs;
    private ArrayList<Mips> MipsText;
    private ArrayList<MIPS.Mips> Mips;
    private ArrayList<Mips> MipsFunc;
    private Stack<SymbolTable> tables;
    private static int str_index;       //.asciiz
    private int funcDefineSp = 0;

    private HashMap<String, Boolean> map = new HashMap<>();  //临时存储
    //private static int mapIndex = 8;
    private final int data = 0x10010000;
    private final int heap = 0x10040000;
    private final int SP = 0x7fffeffc;
    private int hp = 0x10040000;
    private int dataHp = 0x10010000;
    private int sp = 0;
    private int arraySp = 0;

    public AnalyseMips(ArrayList<Quaternion> IRs) {
        this.IRs = IRs;
        this.Mips = new ArrayList<>();
        this.tables = new Stack<>();
        this.MipsText = new ArrayList<>();
        this.MipsFunc = new ArrayList<>();
        initMap();
        str_index = 0;
    }

    public void addHP() {
        this.hp = this.hp + 4;
    }

    public void addDataHp() {
        this.dataHp = this.dataHp + 4;
    }

    public void changeSp(int a) {
        this.sp = this.sp + a;
    }

    public void initMap() {
        for (int i = 8; i <= 25; i++) {
            this.map.put("$" + i, false);
        }
    }

    public String findMap() {
        String str = "";
        for (String i : map.keySet()) {
            if (map.get(i)) {
                continue;
            } else {
                str = i;
                map.put(i, true);
                break;
            }
        }
        return str;
    }

    public void freeMap(String i) {
        map.put(i, false);
        tables.peek().getTableMap().remove(i);
    }

    public String getAddrStr(int addr) {
        return "0x" + Integer.toHexString(addr);
    }

    public Pairs containsIdent(String token) {
        Pairs result = null;
        SymbolTable table = null;
        for (SymbolTable i : tables) {
            if (i.tableMap.containsKey(token)) {
                table = i;
                result = i.tableMap.get(token);
            }
        }
        return result;
    }

    public HashMap<String, Pairs> getAllRegister() {
        HashMap<String, Pairs> result = new HashMap<>();
        for (Pairs i : tables.peek().getTableMap().values()) {
            if (i.getToken().contains("$")) {
                result.put(i.getToken(), i);
            } else if (i.getToken().contains("&")) {
                if (map.get(i.getReg())) {
                    result.put(i.getReg(), i);
                }
            }
        }
        return result;
    }

    public ArrayList<Mips> getMips() {
        return this.Mips;
    }

    public ArrayList<Mips> getMipsText() {
        return this.MipsText;
    }

    public ArrayList<Mips> getMipsFunc() {
        return this.MipsFunc;
    }

    public void changeFuncDefineSp(int num) {
        this.funcDefineSp = this.funcDefineSp + num;
    }

    public Boolean isArray(Pairs pairs) {
        return pairs.getKind().equals(Pairs.Kind.ARRAY_VAR) || pairs.getKind().equals(Pairs.Kind.ARRAY_VAL);
    }

    public String transToReg(String str) {
        str = "&26";
        String temp = str.split("&")[1];
        if (Integer.parseInt(temp) > 25) {
            return findMap();
        } else {
            return temp;
        }
    }

    public Boolean isTempDefine(String str) {
        String temp = str.split("&")[1];
        if (Integer.parseInt(temp) > 25) {
            return true;
        } else {
            return false;
        }
    }

    public void buildMips() {
        SymbolTable table = new SymbolTable();
        tables.push(table);
        MLabel mLabel = new MLabel(MIPS.Mips.Operate.DATA);
        MipsText.add(mLabel);
        MLabel mLabel1 = new MLabel(MIPS.Mips.Operate.TEXT);
        Mips.add(mLabel1);
        for (int i = 0; i < IRs.size(); i++) {
            Quaternion temp = IRs.get(i);
            if (temp instanceof Label) {
                if (((Label) temp).getType().equals("global")) {
                    i = processGlobal(i);
                    initMap();
                } else if (((Label) temp).getType().equals("func")) {
                    i = processFunc(i);
                    initMap();
                } else if (((Label) temp).getType().equals("main")) {
                    i = processMain(i);
                }
            }
        }
        //Binary li = new Binary(MIPS.Mips.Operate.LI,"$2","10");
        //Syscall syscall = new Syscall(10);
        //Mips.add(syscall);
    }

    public int processGlobal(int i) {
        MLabel mLabel = new MLabel("global_begin");
        MipsText.add(mLabel);
        i++;
        while (!(IRs.get(i) instanceof Label) || !((Label) IRs.get(i)).getType().equals("global")) {
            Quaternion globalDefine = IRs.get(i);
            if (globalDefine instanceof Define) {
                if (((Define) globalDefine).getType() == 1) {
                    MLabel mLabel1 = new MLabel(((Define) globalDefine).getPair_a().getToken());
                    MipsText.add(mLabel1);
                    Global global = new Global(((Define) globalDefine).getAnswer().getValue());
                    MipsText.add(global);
                    //Pairs pairs = new Pairs(((Define) globalDefine).getPair_a().getKind(),((Define) globalDefine).getPair_a().getToken());
                    ((Define) globalDefine).getPair_a().setValue(((Define) globalDefine).getAnswer().getValue());
                    ((Define) IRs.get(i)).getPair_a().setAddress(dataHp);
                    addDataHp();
                    tables.peek().addPair(((Define) globalDefine).getPair_a());
                } else {
                    if (!(((Define) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.ARRAY_VAL)
                            || ((Define) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.ARRAY_VAR))) {
                        MLabel mLabel1 = new MLabel(((Define) globalDefine).getPair_a().getToken());
                        MipsText.add(mLabel1);
                        Global global = new Global(0);
                        MipsText.add(global);
                        ((Define) globalDefine).getPair_a().setValue(0);
                        ((Define) IRs.get(i)).getPair_a().setAddress(dataHp);
                        addDataHp();
                        tables.peek().addPair(((Define) globalDefine).getPair_a());
                    } else {
                        ((Define) IRs.get(i)).getPair_a().setAddress(dataHp);
                        tables.peek().addPair(((Define) globalDefine).getPair_a());
                    }
                }
                //((Define) globalDefine).getPair_a().setAddress(data);
                // tables.peek().addPair(((Define) globalDefine).getPair_a());
            } else if (globalDefine instanceof Assign) {    //数组
                MLabel mLabel1 = new MLabel(((Assign) globalDefine).getPairs().getToken());
                MipsText.add(mLabel1);
                //tables.peek().addPair(((Assign) globalDefine).getPairs());
                while ((IRs.get(i) instanceof Assign)) {
                    Pairs find = containsIdent(((Assign) IRs.get(i)).getAnswer().getToken());
                    if (find != null) {
                        if (isArray(find)) {
                            Global global = new Global(find.values.get(((Assign) IRs.get(i)).getAnswer().getParams().get(0).getValue()));
                            MipsText.add(global);
                        } else {
                            Global global = new Global(find.getValue());
                            MipsText.add(global);
                        }
                    } else {
                        Global global = new Global(((Assign) IRs.get(i)).getAnswer().getValue());
                        MipsText.add(global);
                    }
                    addDataHp();
                    i++;
                }
                i--;
            } else {
            }
            i++;
        }
        int flag = 1;
        MLabel mLabelEnd = new MLabel("global_end");
        MipsText.add(mLabelEnd);
        return i;
    }

    public int processFunc(int i) {
        MLabel mLabel = new MLabel(((Label) IRs.get(i)).getPairs().getToken());
        i++;
        HashMap<String, Integer> addrMap = new HashMap<>();
        int index = 0;
        while (!(IRs.get(i) instanceof Label) || !((Label) IRs.get(i)).getType().equals("func")) {
            if (IRs.get(i) instanceof FuncDefine) {
                if (((FuncDefine) IRs.get(i)).getType() == 0) {
                    //CalRI push = new CalRI()
                    MLabel func = new MLabel(((FuncDefine) IRs.get(i)).getFunc().getToken());
                    MipsFunc.add(func);
                    tables.peek().addPair(((FuncDefine) IRs.get(i)).getFunc());
                    SymbolTable table = new SymbolTable();
                    tables.add(table);
                } else {
                    if (!(((FuncDefine) IRs.get(i)).getParam().getKind().equals(Pairs.Kind.ARRAY_VAR)
                            || ((FuncDefine) IRs.get(i)).getParam().getKind().equals(Pairs.Kind.ARRAY_VAL))) {
                        index = index - 4;
                        addrMap.put(((FuncDefine) IRs.get(i)).getParam().getToken(), index);
                        ((FuncDefine) IRs.get(i)).getParam().setIsParam();
                        tables.peek().addPair(((FuncDefine) IRs.get(i)).getParam());
                    } else {
                        index = index - 4;
                        addrMap.put(((FuncDefine) IRs.get(i)).getParam().getToken(), index);
                        ((FuncDefine) IRs.get(i)).getParam().setIsParam();
                        /*if (!isArray(((FuncDefine) IRs.get(i)).getParam().getParams().get(0))) {
                            Pairs temp = containsIdent(((FuncDefine) IRs.get(i)).getParam().getParams().get(0).getToken());

                        }*/
                        tables.peek().addPair(((FuncDefine) IRs.get(i)).getParam());
                    }
                }
            } else {
                if (index < 0) {
                    //changeSp(-4 * (addrMap.size() + 1));
                    for (String str : addrMap.keySet()) {
                        int temp = addrMap.get(str);
                        addrMap.put(str, temp + (addrMap.size() + 1) * 4);
                        containsIdent(str).setAddress(addrMap.get(str));
                    }
                    index = 1;
                }
                i = processBlock(i, MipsFunc, 1);
            }
            i++;
        }
        changeFuncDefineSp(-funcDefineSp);
        Jump jr = new Jump(MIPS.Mips.Operate.JR, "$31");
        MipsFunc.add(jr);
        tables.pop();
        /*if (index == 1) {
            changeSp(4 * (addrMap.size() + 1));
        }*/
        return i;
    }

    public int processMain(int i) {
        MLabel mLabel = new MLabel("main_begin");
        Mips.add(mLabel);
        SymbolTable table = new SymbolTable();
        tables.add(table);
        i++;
        while (!(IRs.get(i) instanceof Label) || !((Label) IRs.get(i)).getType().equals("main")) {
            i = processBlock(i, Mips, 0);
            i++;
        }
        return i;
    }

    public int processBlock(int i, ArrayList<Mips> Mips, int type) {
        if (IRs.get(i) instanceof PrintOut) {
            if (((PrintOut) IRs.get(i)).getType() == 0) {
                MLabel mLabel1 = new MLabel("str" + str_index);
                MipsText.add(mLabel1);
                Ascii ascii = new Ascii(((PrintOut) IRs.get(i)).getStr());
                MipsText.add(ascii);
                str_index++;
                Binary la = new Binary(MIPS.Mips.Operate.LA, "$4", mLabel1.getStr());
                Mips.add(la);
                Syscall syscall = new Syscall(4);
                Mips.add(syscall);
            } else {
                if (((PrintOut) IRs.get(i)).getExp().getToken().contains("&")) {
                    String temp;
                    temp = containsIdent(((PrintOut) IRs.get(i)).getExp().getToken()).getReg();
                    Binary move = new Binary(MIPS.Mips.Operate.MOVE, "$4", temp);
                    Mips.add(move);
                    freeMap(temp);
                    Syscall syscall = new Syscall(1);
                    Mips.add(syscall);
                } else {
                    Pairs pairs = containsIdent(((PrintOut) IRs.get(i)).getExp().getToken());
                    if (pairs == null) {
                        Binary la = new Binary(MIPS.Mips.Operate.LA, "$4", ((PrintOut) IRs.get(i)).getExp().getToken());
                        Mips.add(la);
                        Syscall syscall = new Syscall(1);
                        Mips.add(syscall);
                    } else {        //还需考虑数组
                        if (isArray(pairs)) {
                            pairs = containsIdent(((PrintOut) IRs.get(i)).getExp().getToken()).clone();
                            pairs.setParams(((PrintOut) IRs.get(i)).getExp().getParams());
                            String temp = processPair(pairs, Mips);
                            /*String address = processPair(((PrintOut) IRs.get(i)).getAddress(), Mips);
                            CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, getAddrStr(pairs.getAddress()), address, 2);*/
                            Binary move = new Binary(MIPS.Mips.Operate.MOVE, "$4", temp);
                            //Mips.add(sll);
                            //Mips.add(lw);
                            Mips.add(move);
                            Syscall syscall = new Syscall(1);
                            Mips.add(syscall);
                            freeMap(temp);
                            //freeMap(address);
                        } else {
                            String temp = findMap();
                            if (pairs.getIsParam()) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(pairs.getAddress()), "$sp", 2);
                                Mips.add(lw);
                            } else {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, getAddrStr(pairs.getAddress()), "$0", 2);
                                Mips.add(lw);
                            }
                            Binary move = new Binary(MIPS.Mips.Operate.MOVE, "$4", temp);
                            Mips.add(move);
                            Syscall syscall = new Syscall(1);
                            Mips.add(syscall);
                            freeMap(temp);
                        }
                    }
                }

            }
        } else if (IRs.get(i) instanceof Assign) {
            i = processAssign(i, Mips, type);
        } else if (IRs.get(i) instanceof Define) {
            if (((Define) IRs.get(i)).getType() == 1) {
                Pairs pairs = containsIdent(((Define) IRs.get(i)).getAnswer().getToken());
                //CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, Integer.toString(map.get(((Define) IRs.get(i)).getAnswer().getToken())), Integer.toOctalString(hp), "$0", 2);
                if (pairs == null) {    //赋值常量
                    String temp = findMap();
                    Binary li = new Binary(MIPS.Mips.Operate.LI, temp, ((Define) IRs.get(i)).getAnswer().getToken());
                    Mips.add(li);
                    if (type == 1) {
                        CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, Integer.toString(funcDefineSp), "$sp", 2);
                        Mips.add(swVal);
                        ((Define) IRs.get(i)).getPair_a().setIsParam();
                        ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                        changeFuncDefineSp(-4);
                    } else {
                        CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(hp), "$0", 2);
                        Mips.add(swVal);
                        ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                        addHP();
                    }
                    freeMap(temp);
                    tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                } else {
                    /*if (pairs.getToken().contains("&")) {
                        String test = pairs.getReg();
                        if (type == 1) {
                            CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, test, getAddrStr(funcDefineSp), "$sp", 2);
                            Mips.add(swVal);
                            ((Define) IRs.get(i)).getPair_a().setIsParam();
                            ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                            changeFuncDefineSp(-4);
                        } else {
                            CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, test, getAddrStr(hp), "$0", 2);
                            Mips.add(swVal);
                            ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                            addHP();
                        }
                        ((Define) IRs.get(i)).getPair_a().setReg(test);
                        freeMap(test);
                        tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                    } else {
                        if (pairs.getInit()) {
                            String temp = findMap();
                            Binary li = new Binary(MIPS.Mips.Operate.LI, temp, Integer.toString(pairs.getValue()));
                            Mips.add(li);
                            if (type == 1) {
                                CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(funcDefineSp), "$sp", 2);
                                Mips.add(swVal);
                                ((Define) IRs.get(i)).getPair_a().setIsParam();
                                ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                                changeFuncDefineSp(-4);
                            } else {
                                CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(hp), "$0", 2);
                                Mips.add(swVal);
                                ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                                addHP();
                            }
                            freeMap(temp);
                            tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                        } else {
                            String temp = findMap();
                            if (pairs.getIsParam()) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(pairs.getAddress()), "$sp", 2);
                                Mips.add(lw);
                            } else {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, getAddrStr(pairs.getAddress()), "$0", 2);
                                Mips.add(lw);
                            }
                            if (type == 1) {
                                CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(funcDefineSp), "$sp", 2);
                                Mips.add(swVal);
                                ((Define) IRs.get(i)).getPair_a().setIsParam();
                                ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                                changeFuncDefineSp(-4);
                            } else {
                                CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(hp), "$0", 2);
                                Mips.add(swVal);
                                ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                                addHP();
                            }
                            freeMap(temp);
                            tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                        }
                    }*/
                    if (isArray(pairs)) {
                        pairs = containsIdent(((Define) IRs.get(i)).getAnswer().getToken()).clone();
                        pairs.setParams(((Define) IRs.get(i)).getAnswer().getParams());
                    }
                    String right = processPair(pairs, Mips);
                    if (type == 1) {
                        CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, right, Integer.toString(funcDefineSp), "$sp", 2);
                        Mips.add(swVal);
                        ((Define) IRs.get(i)).getPair_a().setIsParam();
                        ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                        changeFuncDefineSp(-4);
                    } else {
                        CalRI swVal = new CalRI(MIPS.Mips.Operate.SW, right, getAddrStr(hp), "$0", 2);
                        Mips.add(swVal);
                        ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                        addHP();
                    }
                    freeMap(right);
                    tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                }
            } else {
                if (!(((Define) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.ARRAY_VAL)
                        || ((Define) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.ARRAY_VAR))) {
                    Pairs pairs = ((Define) IRs.get(i)).getPair_a();
                    if (type == 1) {
                        ((Define) IRs.get(i)).getPair_a().setIsParam();
                        ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp);
                        changeFuncDefineSp(-4);
                    } else {
                        ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                        addHP();
                    }
                    tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                } else {
                    int flag = 1;
                    Pairs pairs = ((Define) IRs.get(i)).getPair_a();
                    if (type == 1) {
                        ((Define) IRs.get(i)).getPair_a().setIsParam();
                        int addr;
                        if (((Define) IRs.get(i)).getPair_dim2() == null) {
                            addr = ((Define) IRs.get(i)).getPair_dim1().getValue() * 4;
                        } else {
                            addr = ((Define) IRs.get(i)).getPair_dim1().getValue() * ((Define) IRs.get(i)).getPair_dim2().getValue() * 4;
                        }
                        changeFuncDefineSp(-addr);
                        //changeFuncDefineSp(4);
                        arraySp = funcDefineSp;
                        ((Define) IRs.get(i)).getPair_a().setAddress(funcDefineSp+4);
                    } else {
                        ((Define) IRs.get(i)).getPair_a().setAddress(hp);
                        int addr;
                        if (((Define) IRs.get(i)).getPair_dim2() == null) {
                            addr = ((Define) IRs.get(i)).getPair_dim1().getValue() * 4;
                        } else {
                            addr = ((Define) IRs.get(i)).getPair_dim1().getValue() * ((Define) IRs.get(i)).getPair_dim2().getValue() * 4;
                        }
                        hp = hp + addr;
                    }
                    tables.peek().addPair(((Define) IRs.get(i)).getPair_a());
                }
            }
        } else if (IRs.get(i) instanceof Expression) {
            //map.put(((Expression) IRs.get(i)).getAnswer().getToken(), true);
            /*if (((Expression) IRs.get(i)).getAnswer().getInit()) {
                Binary li = new Binary(MIPS.Mips.Operate.LI, ((Expression) IRs.get(i)).getAnswer().getToken(), Integer.toString(((Expression) IRs.get(i)).getAnswer().getValue()));
                Mips.add(li);
                //map.put(((Expression) IRs.get(i)).getAnswer().getToken(), ((Expression) IRs.get(i)).getAnswer().getValue());
                tables.peek().addPair(((Expression) IRs.get(i)).getAnswer());

            } else */
            if (((Expression) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.RET) || ((Expression) IRs.get(i)).getPair_b().getKind().equals(Pairs.Kind.RET)) {
                //无用.........
                /*String tempA = "";
                String tempB = "";
                Binary moveA = null;
                Binary moveB = null;
                Pairs pa = containsIdent(((Expression) IRs.get(i)).getPair_a().getToken());
                Pairs pb = containsIdent(((Expression) IRs.get(i)).getPair_b().getToken());
                if (((Expression) IRs.get(i)).getPair_a().getKind().equals(Pairs.Kind.RET)) {
                    tempA = findMap();
                    moveA = new Binary(MIPS.Mips.Operate.MOVE, tempA, "$2");
                    Mips.add(moveA);
                    if (((Expression) IRs.get(i)).getPair_b().getKind().equals(Pairs.Kind.RET)) {
                        tempB = findMap();
                        moveB = new Binary(MIPS.Mips.Operate.MOVE, tempB, "$2");
                        Mips.add(moveB);
                    } else {
                        if (pb != null) {
                            if (pb.getToken().contains("$")) {
                                tempB = pb.getToken();
                            } else {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, tempB, getAddrStr(pb.getAddress()), "$0", 2);
                                Mips.add(lw);
                            }
                        } else {    //数字

                        }
                    }
                }*/
            } else {
                Pairs pa = containsIdent(((Expression) IRs.get(i)).getPair_a().getToken());
                Pairs pb = containsIdent(((Expression) IRs.get(i)).getPair_b().getToken());
                if (pb == null) {
                    pb = ((Expression) IRs.get(i)).getPair_b();
                } else {
                    if (isArray(((Expression) IRs.get(i)).getPair_b())) {
                        pb = containsIdent(((Expression) IRs.get(i)).getPair_b().getToken()).clone();
                        pb.setParams(((Expression) IRs.get(i)).getPair_b().getParams());
                    }
                }
                if (pa == null) {
                    pa = ((Expression) IRs.get(i)).getPair_a();
                } else {
                    if (isArray(((Expression) IRs.get(i)).getPair_a())) {
                        pa = containsIdent(((Expression) IRs.get(i)).getPair_a().getToken()).clone();
                        pa.setParams(((Expression) IRs.get(i)).getPair_a().getParams());
                    }
                }
                Expression exp = ((Expression) IRs.get(i));
                switch (IRs.get(i).getOp()) {
                    case ADD:
                        String temp11;
                        String temp12;
                        temp11 = processPair(pa, Mips);
                        temp12 = processPair(pb, Mips);
                        String ans1 = transToReg(exp.getAnswer().getToken());
                        CalRI add = new CalRI(MIPS.Mips.Operate.ADDU, ans1, temp11, temp12, 1);
                        Mips.add(add);
                        freeMap(temp11);
                        freeMap(temp12);
                        exp.getAnswer().setReg(ans1);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case SUB:
                        String temp21;
                        String temp22;
                        temp21 = processPair(pa, Mips);
                        temp22 = processPair(pb, Mips);
                        String ans2 = transToReg(exp.getAnswer().getToken());
                        CalRI sub = new CalRI(MIPS.Mips.Operate.SUBU, ans2, temp21, temp22, 1);
                        Mips.add(sub);
                        freeMap(temp21);
                        freeMap(temp22);
                        exp.getAnswer().setReg(ans2);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case SLT:
                        String temp61;
                        String temp62;
                        temp61 = processPair(pa, Mips);
                        temp62 = processPair(pb, Mips);
                        String an6 = transToReg(exp.getAnswer().getToken());
                        CalRI slt = new CalRI(MIPS.Mips.Operate.SLT, an6, temp61, temp62, 1);
                        Mips.add(slt);
                        freeMap(temp61);
                        freeMap(temp62);
                        exp.getAnswer().setReg(an6);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case SLTIU:
                        String temp71;
                        temp71 = processPair(pa, Mips);
                        //temp72 = processPair(pb,temp72,Mips);
                        String ans7 = transToReg(exp.getAnswer().getToken());
                        CalRI sltiu = new CalRI(MIPS.Mips.Operate.SLTIU, ans7, temp71, "1", 1);
                        Mips.add(sltiu);
                        freeMap(temp71);
                        exp.getAnswer().setReg(ans7);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case XOR:
                        String temp81;
                        String temp82;
                        temp81 = processPair(pa, Mips);
                        temp82 = processPair(pb, Mips);
                        String an8 = transToReg(exp.getAnswer().getToken());
                        CalRI xor = new CalRI(MIPS.Mips.Operate.XOR, an8, temp81, temp82, 1);
                        Mips.add(xor);
                        freeMap(temp81);
                        freeMap(temp82);
                        exp.getAnswer().setReg(an8);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case MULT:
                        String temp31;
                        String temp32;
                        temp31 = processPair(pa, Mips);
                        temp32 = processPair(pb, Mips);
                        Binary mul = new Binary(MIPS.Mips.Operate.MULI, temp31, temp32);
                        String ans3 = transToReg(exp.getAnswer().getToken());
                        Binary move1 = new Binary(MIPS.Mips.Operate.MFLO, ans3, "$lo");
                        Mips.add(mul);
                        Mips.add(move1);
                        freeMap(temp31);
                        freeMap(temp32);
                        exp.getAnswer().setReg(ans3);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case MOD:
                        String temp41;
                        String temp42;
                        temp41 = processPair(pa, Mips);
                        temp42 = processPair(pb, Mips);
                        Binary mod = new Binary(MIPS.Mips.Operate.DIV, temp41, temp42);
                        String ans4 = transToReg(exp.getAnswer().getToken());
                        Binary move2 = new Binary(MIPS.Mips.Operate.MFHI, ans4, "$hi");
                        Mips.add(mod);
                        Mips.add(move2);
                        freeMap(temp41);
                        freeMap(temp42);
                        exp.getAnswer().setReg(ans4);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                    case DIV:
                        String temp51;
                        String temp52;
                        temp51 = processPair(pa, Mips);
                        temp52 = processPair(pb, Mips);
                        Binary div = new Binary(MIPS.Mips.Operate.DIV, temp51, temp52);
                        String ans5 = transToReg(exp.getAnswer().getToken());
                        Binary move3 = new Binary(MIPS.Mips.Operate.MFLO, ans5, "$lo");
                        Mips.add(div);
                        Mips.add(move3);
                        freeMap(temp51);
                        freeMap(temp52);
                        exp.getAnswer().setReg(ans5);
                        tables.peek().addPair(exp.getAnswer());
                        break;
                }
                //map.put(exp.getAnswer().getToken(),true);
            }
            int flag = 1;
            //map.put(((Expression) IRs.get(i)).getAnswer().getToken(), false);
        } else if (IRs.get(i) instanceof FuncCallRet) {
            if (IRs.get(i).getOp().equals(Quaternion.OP.RET)) {        //RET
                if (((FuncCallRet) IRs.get(i)).getrParam() == null) {
                    Jump jr = new Jump(MIPS.Mips.Operate.JR, "$31");
                    Mips.add(jr);
                } else {
                    if (((FuncCallRet) IRs.get(i)).getAddress() == null) {
                        Pairs ret = containsIdent(((FuncCallRet) IRs.get(i)).getrParam().getToken());
                        if (ret == null) {
                            ret = ((FuncCallRet) IRs.get(i)).getrParam();
                            Binary li = new Binary(MIPS.Mips.Operate.LI, "$2", ret.getToken());
                            Mips.add(li);
                            Pairs pairs = new Pairs(Pairs.Kind.VAL, "$2");
                            pairs.setValue(ret.getValue());
                            tables.peek().addPair(pairs);
                        } else {
                            if (ret.getIsParam()) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, "$2", Integer.toString(ret.getAddress()), "$sp", 2);
                                Mips.add(lw);
                                Pairs pairs = new Pairs(Pairs.Kind.VAL, "$2");
                                pairs.setValue(ret.getValue());
                                tables.peek().addPair(pairs);
                            } else {
                                if (ret.getToken().contains("&")) {
                                    //String test = transToReg(ret.getToken());
                                    String test = ret.getReg();
                                    Binary move = new Binary(MIPS.Mips.Operate.MOVE, "$2", test);
                                    Mips.add(move);
                                    Pairs pairs = new Pairs(Pairs.Kind.VAL, "$2");
                                    pairs.setValue(ret.getValue());
                                    //pairs.setReg(test);
                                    tables.peek().addPair(pairs);
                                } else {
                                    CalRI lw = new CalRI(MIPS.Mips.Operate.LW, "$2", getAddrStr(ret.getAddress()), "$0", 2);
                                    Mips.add(lw);
                                    Pairs pairs = new Pairs(Pairs.Kind.VAL, "$2");
                                    pairs.setValue(ret.getValue());
                                    tables.peek().addPair(pairs);
                                }
                            }
                        }
                    } else {    //数组
                    }
                    if (type == 1) {
                        Jump jr = new Jump(MIPS.Mips.Operate.JR, "$31");
                        Mips.add(jr);
                    }
                    if (type == 0) {
                        Syscall syscall = new Syscall(10);
                        Mips.add(syscall);
                    }
                }
            } else {
                int beginSp = sp;
                changeSp(-beginSp);
                changeSp(funcDefineSp);
                HashSet<Mips> returnList = new HashSet<>();
                //changeSp(-4);
                CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$31", Integer.toString(sp), "$sp", 2);
                Mips.add(sw);
                CalRI lw1 = new CalRI(MIPS.Mips.Operate.LW, "$31", Integer.toString(sp), "$sp", 2);
                changeSp(-4);
                returnList.add(lw1);
                HashMap<String, Pairs> registers = getAllRegister();
                HashSet<String> already = new HashSet<>();
                for (Pairs j : registers.values()) {
                    if (already.contains(j.getToken())) {
                        continue;
                    } else {
                        already.add(j.getToken());
                    }
                    if (j.getToken().equals("$2")) {
                        continue;
                    }
                    String temp;
                    if (j.getToken().contains("&")) {
                        temp = j.getReg();
                    } else {
                        temp = j.getToken();
                    }
                    CalRI swR = new CalRI(MIPS.Mips.Operate.SW, temp, Integer.toString(sp), "$sp", 2);
                    Mips.add(swR);
                    CalRI lwR = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(sp), "$sp", 2);
                    returnList.add(lwR);
                    changeSp(-4);
                }
                while (!(IRs.get(i) instanceof FuncCallRet && IRs.get(i).getOp().equals(Quaternion.OP.CALL))) {
                    if (IRs.get(i) instanceof FuncCallRet && IRs.get(i).getOp().equals(Quaternion.OP.PUSH)) {
                        FuncCallRet func = ((FuncCallRet) IRs.get(i));
                        if (func.getAddress() == null) {        //还要传数组
                            if (isArray(func.getrParam())) {
                                Pairs pairs = containsIdent(func.getrParam().getToken());
                                if (pairs == null) {
                                    pairs = func.getrParam();
                                } else {
                                    pairs = containsIdent(func.getrParam().getToken()).clone();
                                    pairs.setParams(func.getrParam().getParams());
                                }
                                //String temp = processPair(pairs, Mips);
                                String temp = findMap();
                                if (pairs.getIsParam()) {
                                    if (pairs.getAddress() > 0) {
                                        CalRI lwA = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(pairs.getAddress()), "$sp", 2);
                                        Mips.add(lwA);
                                    } else {
                                        Binary li = new Binary(MIPS.Mips.Operate.LI, temp, getAddrStr(pairs.getAddress()));
                                        Mips.add(li);
                                        CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp,temp,"$sp",1);
                                        Mips.add(addu);
                                    }
                                    CalRI swA = new CalRI(MIPS.Mips.Operate.SW, temp, Integer.toString(sp), "$sp", 2);
                                    Mips.add(swA);
                                } else {
                                    Binary li = new Binary(MIPS.Mips.Operate.LI, temp, getAddrStr(pairs.getAddress()));
                                    CalRI swA = new CalRI(MIPS.Mips.Operate.SW, temp, Integer.toString(sp), "$sp", 2);
                                    Mips.add(li);
                                    Mips.add(swA);
                                }
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(sp), "$sp", 2);
                                returnList.add(lw);
                                freeMap(temp);
                                changeSp(-4);
                            } else {
                                String temp = findMap();
                                if (func.getrParam().getKind().equals(Pairs.Kind.NUM)) {
                                    Binary li = new Binary(MIPS.Mips.Operate.LI, temp, func.getrParam().getToken());
                                    Mips.add(li);
                                    freeMap(temp);
                                } else {
                                    Pairs pairs = containsIdent(func.getrParam().getToken());
                                    if (pairs.getToken().contains("&")) {
                                        freeMap(temp);
                                        temp = pairs.getReg();
                                        freeMap(temp);
                                    } else {
                                        if (pairs.getIsParam()) {
                                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(pairs.getAddress()), "$sp", 2);
                                            Mips.add(lw);
                                        } else {
                                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, getAddrStr(pairs.getAddress()), "$0", 2);
                                            Mips.add(lw);
                                        }
                                        freeMap(temp);
                                    }
                                }
                                CalRI sw1 = new CalRI(MIPS.Mips.Operate.SW, temp, Integer.toString(sp), "$sp", 2);
                                Mips.add(sw1);
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(sp), "$sp", 2);
                                returnList.add(lw);
                                changeSp(-4);
                            }
                        } else {        //数组
                            Pairs pairs = containsIdent(func.getrParam().getToken());
                            if (pairs == null) {
                                pairs = func.getrParam();
                            } else if (isArray(func.getrParam())) {
                                pairs = containsIdent(func.getrParam().getToken()).clone();
                                pairs.setParams(func.getrParam().getParams());
                            }
                            Pairs addrA = containsIdent(func.getAddress().getToken());
                            if (addrA == null) {
                                addrA = func.getAddress();
                            } else if (isArray(addrA)) {
                                addrA = containsIdent(func.getAddress().getToken()).clone();
                                addrA.setParams(func.getAddress().getParams());
                            }
                            String address = processPair(addrA, Mips);
                            String temp1 = findMap();
                            CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                            Mips.add(sll);
                            if (pairs.getIsParam()) {
                                if (pairs.getAddress() > 0) {
                                    CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp1, Integer.toString(pairs.getAddress()), "$sp", 2);
                                    Mips.add(lw);
                                } else {
                                    Binary li = new Binary(MIPS.Mips.Operate.LI, temp1, getAddrStr(pairs.getAddress()));
                                    Mips.add(li);
                                    CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp1,temp1,"$sp",1);
                                    Mips.add(addu);
                                }
                            } else {
                                Binary li = new Binary(MIPS.Mips.Operate.LI, temp1, getAddrStr(pairs.getAddress()));
                                Mips.add(li);
                            }
                            CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, address, address, temp1, 1);
                            Mips.add(addu);
                            if (func.getrParam().getDim() == 1) {
                                temp1 = address;
                            } else {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp1, "0", address, 2);
                                Mips.add(lw);
                            }
                            CalRI sw1 = new CalRI(MIPS.Mips.Operate.SW, temp1, Integer.toString(sp), "$sp", 2);
                            Mips.add(sw1);
                            CalRI lw2 = new CalRI(MIPS.Mips.Operate.LW, temp1, Integer.toString(sp), "$sp", 2);
                            returnList.add(lw2);
                            changeSp(-4);
                            freeMap(temp1);
                            freeMap(address);
                        }
                    } else {
                        i = processBlock(i, Mips, type);
                    }
                    i++;
                }
                if (IRs.get(i).getOp().equals(Quaternion.OP.CALL)) {
                    CalRI sub = new CalRI(MIPS.Mips.Operate.SUBI, "$sp", "$sp", Integer.toString(-sp), 1);
                    Mips.add(sub);
                    Jump jal = new Jump(MIPS.Mips.Operate.JAL, ((FuncCallRet) IRs.get(i)).getFunc().getToken());
                    Mips.add(jal);
                    CalRI add = new CalRI(MIPS.Mips.Operate.ADDI, "$sp", "$sp", Integer.toString(-sp), 1);
                    Mips.add(add);
                    Mips.addAll(returnList);
                    changeSp(-sp);
                    if (type == 1) {
                        changeSp(beginSp);
                        changeSp(-funcDefineSp);
                    }
                }
            }
        } else if (IRs.get(i) instanceof Cmp) {
            Cmp cmp = (Cmp) IRs.get(i);
            String temp;
            String temp1;
            Pairs pa = containsIdent(cmp.getPairs_a().getToken());
            Pairs pb = containsIdent(cmp.getPairs_b().getToken());
            if (pa == null) {
                pa = cmp.getPairs_a();
            } else {
                if (isArray(cmp.getPairs_a())) {
                    pa = containsIdent(cmp.getPairs_a().getToken()).clone();
                    pa.setParams(cmp.getPairs_a().getParams());
                }
            }
            if (pb == null) {
                pb = cmp.getPairs_b();
            } else {
                if (isArray(cmp.getPairs_b())) {
                    pb = containsIdent(cmp.getPairs_b().getToken()).clone();
                    pb.setParams(cmp.getPairs_b().getParams());
                }
            }
            temp = processPair(pa, Mips);
            temp1 = processPair(pb, Mips);
            //String ans = findMap();
            String label = cmp.getJump().getBranch();
            if (cmp.getJump().getOp().equals(Quaternion.OP.BEQ)) {
                CalRI branch = new CalRI(MIPS.Mips.Operate.BEQ, temp, temp1, label, 3);
                Mips.add(branch);
            } else if (cmp.getJump().getOp().equals(Quaternion.OP.BNE)) {
                CalRI branch = new CalRI(MIPS.Mips.Operate.BNE, temp, temp1, label, 3);
                Mips.add(branch);
            }
            freeMap(temp);
            freeMap(temp1);
        } else if (IRs.get(i) instanceof Label) {
            Label label = (Label) IRs.get(i);
            if (label.getType().equals("if") || label.getType().equals("else") || label.getType().equals("while") || label.getType().equals("w_cond")) {
                MLabel mLabel = new MLabel(label.branchName());
                Mips.add(mLabel);
            } else if (label.getType().equals("block")) {
                MLabel mLabel = new MLabel(label.branchName());
                Mips.add(mLabel);
                if (label.getLabel().equals("begin")) {
                    SymbolTable table = new SymbolTable();
                    tables.add(table);
                } else {
                    tables.pop();
                }
            }
        } else if (IRs.get(i) instanceof BranchJump) {
            if (IRs.get(i).getOp().equals(Quaternion.OP.GOTO)) {
                Jump jump = new Jump(MIPS.Mips.Operate.J, ((BranchJump) IRs.get(i)).getBranch());
                Mips.add(jump);
            }
        }
        return i;
    }

    public int processAssign(int i, ArrayList<Mips> Mips, int type) {
        if (IRs.get(i).getOp().equals(Quaternion.OP.GETINT)) {  //输入
            Syscall syscall = new Syscall(5);
            Mips.add(syscall);
            if (((Assign) IRs.get(i)).getAddress() == null) {
                Pairs pairs = containsIdent(((Assign) IRs.get(i)).getPairs().getToken());
                if (pairs.getIsParam()) {
                    CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$2", Integer.toString(pairs.getAddress()), "$sp", 2);
                    Mips.add(sw);
                } else {
                    CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$2", getAddrStr(pairs.getAddress()), "$0", 2);
                    Mips.add(sw);
                }
                ((Assign) IRs.get(i)).getPairs().setInit(false);
            } else {
                Assign assign = (Assign) IRs.get(i);
                Pairs left = containsIdent(((Assign) IRs.get(i)).getPairs().getToken());
                if (left == null) {
                    left = ((Assign) IRs.get(i)).getPairs();
                } else if (isArray(((Assign) IRs.get(i)).getPairs())) {
                    left = containsIdent(((Assign) IRs.get(i)).getPairs().getToken()).clone();
                    left.setParams(((Assign) IRs.get(i)).getPairs().getParams());
                }
                Pairs pAddr1 = containsIdent(assign.getAddress().getToken());
                if (pAddr1 == null) {
                    pAddr1 = assign.getAddress();
                } else if (isArray(pAddr1)) {
                    pAddr1 = containsIdent(assign.getAddress().getToken()).clone();
                    pAddr1.setParams(assign.getAddress().getParams());
                }
                String address1 = processPair(pAddr1, Mips);
                CalRI sll1 = new CalRI(MIPS.Mips.Operate.SLL, address1, address1, "2", 1);
                Mips.add(sll1);
                if (left.getIsParam()) {
                    String temp3 = findMap();
                    if (left.getAddress() > 0) {
                        CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp3, Integer.toString(left.getAddress()), "$sp", 2);
                        Mips.add(lw);
                        CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                        Mips.add(addu);
                    } else {
                        Binary li = new Binary(MIPS.Mips.Operate.LI, temp3, getAddrStr(left.getAddress()));
                        Mips.add(li);
                        CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp3,temp3,"$sp",1);
                        Mips.add(addu);
                        CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                        Mips.add(subu);
                    }
                    //CalRI lw2 = new CalRI(MIPS.Mips.Operate.LW,temp3,"0",temp3,2);
                    CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$2", "0", temp3, 2);
                    Mips.add(sw);
                    freeMap(temp3);
                } else {
                    CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$2", getAddrStr(left.getAddress()), address1, 2);
                    Mips.add(sw);
                }
                freeMap(address1);
            }
        } else {
            if ((IRs.get(i)).getOp().equals(Quaternion.OP.ARRAY)) {
                Assign assign = ((Assign) IRs.get(i));
                Pairs pb = containsIdent(assign.getAnswer().getToken());
                Pairs pa = containsIdent(assign.getPairs().getToken());
                if (pb == null) {
                    pb = assign.getAnswer();
                } else {
                    if (isArray(((Assign) IRs.get(i)).getAnswer())) {
                        pb = containsIdent(((Assign) IRs.get(i)).getAnswer().getToken()).clone();
                        pb.setParams(((Assign) IRs.get(i)).getAnswer().getParams());
                    }
                }
                if (pa == null) {
                    pa = assign.getPairs();
                } else {
                    if (isArray(((Assign) IRs.get(i)).getPairs())) {
                        pa = containsIdent(((Assign) IRs.get(i)).getPairs().getToken()).clone();
                        pa.setParams(((Assign) IRs.get(i)).getPairs().getParams());
                    }
                }
                if (type == 1) {
                    String temp = findMap();
                    String ans = processPair(pb, Mips);
                    //Binary move = new Binary(MIPS.Mips.Operate.MOVE, temp, ans);
                    //String address = processPair(assign.getAddress(),Mips);
                    //CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                    arraySp = arraySp + 4;
                    CalRI sw = new CalRI(MIPS.Mips.Operate.SW, ans, Integer.toString(arraySp), "$sp", 2);
                    // Mips.add(move);
                    Mips.add(sw);
                    freeMap(temp);
                    freeMap(ans);
                    //changeFuncDefineSp(-4);
                    //changeFuncDefineSp(-4);
                } else {
                    Pairs addr1 = containsIdent(assign.getAddress().getToken());
                    if (addr1 == null) {
                        addr1 = assign.getAddress();
                    } else if (isArray(addr1)) {
                        addr1 = containsIdent(assign.getAddress().getToken()).clone();
                        addr1.setParams(assign.getAddress().getParams());
                    }
                    /*if (pb == null) {
                        String temp = findMap();
                        //String ans = processPair(assign.getAnswer(),Mips);
                        Binary li = new Binary(MIPS.Mips.Operate.LI, temp, assign.getAnswer().getToken());
                        Mips.add(li);
                        String address1 = processPair(addr1, Mips);
                        CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address1, address1, "2", 1);
                        CalRI sw = new CalRI(MIPS.Mips.Operate.SW, temp, getAddrStr(pa.getAddress()), address1, 2);
                        Mips.add(sll);
                        Mips.add(sw);
                        freeMap(temp);
                        freeMap(address1);
                    } else {*/
                        String ans = processPair(pb, Mips);
                        String address = processPair(addr1, Mips);
                        //Binary move = new Binary(MIPS.Mips.Operate.MOVE, temp, address);
                        CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                        //CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,address,address,)
                        CalRI sw = new CalRI(MIPS.Mips.Operate.SW, ans, getAddrStr(pa.getAddress()), address, 2);
                        Mips.add(sll);
                        Mips.add(sw);
                        freeMap(address);
                        freeMap(ans);

                }
            } else {
                Assign assign = ((Assign) IRs.get(i));
                Pairs right = containsIdent(((Assign) IRs.get(i)).getAnswer().getToken());
                Pairs left = containsIdent(((Assign) IRs.get(i)).getPairs().getToken());
                if (right == null) {
                    right = ((Assign) IRs.get(i)).getAnswer();
                } else if (isArray(((Assign) IRs.get(i)).getAnswer())) {
                    right = containsIdent(((Assign) IRs.get(i)).getAnswer().getToken()).clone();
                    right.setParams(((Assign) IRs.get(i)).getAnswer().getParams());
                }
                if (left == null) {
                    left = ((Assign) IRs.get(i)).getPairs();
                } else if (isArray(((Assign) IRs.get(i)).getPairs())) {
                    left = containsIdent(((Assign) IRs.get(i)).getPairs().getToken()).clone();
                    left.setParams(((Assign) IRs.get(i)).getPairs().getParams());
                }
                if (((Assign) IRs.get(i)).getAddress() == null) {
                    if (((Assign) IRs.get(i)).getAddress2() == null) {
                        if (((Assign) IRs.get(i)).getAnswer().getKind().equals(Pairs.Kind.RET)) {
                            //Pairs pairs = containsIdent(((Assign) IRs.get(i)).getPairs().getToken());
                            //CalRI sw = new CalRI(MIPS.Mips.Operate.SW, "$2", getAddrStr(pairs.getAddress()), "$0", 2);
                            //Mips.add(sw);
                            String temp = transToReg(((Assign) IRs.get(i)).getPairs().getToken());
                            Binary move = new Binary(MIPS.Mips.Operate.MOVE, temp, "$2");
                            Mips.add(move);
                            //map.put(((Assign) IRs.get(i)).getPairs().getToken(), true);
                            map.put(temp, true);
                            ((Assign) IRs.get(i)).getPairs().setReg(temp);
                        } else {
                            String temp1;
                            //String temp2 = findMap();
                            temp1 = processPair(right, Mips);
                            if (left.getIsParam()) {
                                CalRI sw = new CalRI(MIPS.Mips.Operate.SW, temp1, Integer.toString(left.getAddress()), "$sp", 2);
                                Mips.add(sw);
                            } else {
                                CalRI sw = new CalRI(MIPS.Mips.Operate.SW, temp1, getAddrStr(left.getAddress()), "$0", 2);
                                Mips.add(sw);
                            }
                            freeMap(temp1);
                            //  tables.peek().addPair(((Assign) IRs.get(i)).getPairs());
                        }
                    } else {
                        //String address = processPair(assign.getAddress2(),Mips);
                        if (right.getParams().isEmpty()) {
                            right.getParams().add(assign.getAddress2());
                        }
                        Pairs address2 = containsIdent(assign.getAddress2().getToken());
                        if (address2 == null) {
                            address2 = assign.getAddress2();
                        } else if (isArray(address2)) {
                            address2 = containsIdent(assign.getAddress2().getToken()).clone();
                            address2.setParams(assign.getAddress2().getParams());
                        }
                        String right1 = findMap();
                        if (right.getIsParam()) {
                            String temp1 = findMap();
                            String address = processPair(address2, Mips);
                            CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                            Mips.add(sll);
                            if (right.getAddress() > 0) {
                                CalRI lwA = new CalRI(MIPS.Mips.Operate.LW, temp1, Integer.toString(right.getAddress()), "$sp", 2);
                                Mips.add(lwA);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp1, temp1, address, 1);
                                Mips.add(addu);
                            } else {
                                Binary li = new Binary(MIPS.Mips.Operate.LI, temp1, getAddrStr(right.getAddress()));
                                Mips.add(li);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp1,temp1,"$sp",1);
                                Mips.add(addu);
                                CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU, temp1, temp1, address, 1);
                                Mips.add(subu);
                            }
                            //Binary li = new Binary(MIPS.Mips.Operate.LI,temp1,getAddrStr(pa.getAddress()));
                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, right1, "0", temp1, 2);
                            //Mips.add(li);
                            Mips.add(lw);
                            freeMap(address);
                            freeMap(temp1);
                        } else {
                            String temp1 = findMap();
                            String address = processPair(address2, Mips);
                            CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                            //CalRI lwA = new CalRI(MIPS.Mips.Operate.LW,temp1,getAddrStr(pa.getAddress()),"$0",2);
                            Binary li = new Binary(MIPS.Mips.Operate.LI, temp1, getAddrStr(right.getAddress()));
                            CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp1, temp1, address, 1);
                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, right1, "0", temp1, 2);
                            Mips.add(sll);
                            Mips.add(li);
                            Mips.add(addu);
                            Mips.add(lw);
                            freeMap(address);
                            freeMap(temp1);
                        }
                        if (left.getIsParam()) {
                            CalRI sw = new CalRI(MIPS.Mips.Operate.SW, right1, Integer.toString(left.getAddress()), "$sp", 2);
                            Mips.add(sw);
                        } else {
                            String reg;
                            if (left.getToken().contains("&")) {
                                Pairs temp = containsIdent(left.getToken());
                                if (temp != null) {
                                    reg = temp.getReg();
                                } else {
                                    reg = transToReg(left.getToken());
                                }
                                ((Assign) IRs.get(i)).getPairs().setReg(reg);
                                Binary move = new Binary(MIPS.Mips.Operate.MOVE, reg, right1);
                                Mips.add(move);
                            } else {
                                CalRI sw = new CalRI(MIPS.Mips.Operate.SW, right1, getAddrStr(left.getAddress()), "$0", 2);
                                Mips.add(sw);
                            }
                        }
                        freeMap(right1);
                        // tables.peek().addPair(((Assign) IRs.get(i)).getPairs());
                    }
                } else {
                    if (((Assign) IRs.get(i)).getAddress2() == null) {
                        //tables.peek().addPair(((Assign) IRs.get(i)).getPairs());
                        String right1 = processPair(right, Mips);
                        Pairs pAddr1 = containsIdent(assign.getAddress().getToken());
                        if (pAddr1 == null) {
                            pAddr1 = assign.getAddress();
                        } else if (isArray(pAddr1)) {
                            pAddr1 = containsIdent(assign.getAddress().getToken()).clone();
                            pAddr1.setParams(assign.getAddress().getParams());
                        }
                        String address1 = processPair(pAddr1, Mips);
                        CalRI sll1 = new CalRI(MIPS.Mips.Operate.SLL, address1, address1, "2", 1);
                        Mips.add(sll1);
                        if (left.getIsParam()) {
                            String temp3 = findMap();
                            if (left.getAddress() > 0) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp3, Integer.toString(left.getAddress()), "$sp", 2);
                                Mips.add(lw);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                                Mips.add(addu);
                            } else {
                                Binary li = new Binary(MIPS.Mips.Operate.LI, temp3, getAddrStr(left.getAddress()));
                                Mips.add(li);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp3,temp3,"$sp",1);
                                Mips.add(addu);
                                CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                                Mips.add(subu);
                            }
                            //CalRI lw2 = new CalRI(MIPS.Mips.Operate.LW,temp3,"0",temp3,2);
                            CalRI sw = new CalRI(MIPS.Mips.Operate.SW, right1, "0", temp3, 2);
                            Mips.add(sw);
                            freeMap(temp3);
                        } else {
                            CalRI sw = new CalRI(MIPS.Mips.Operate.SW, right1, getAddrStr(left.getAddress()), address1, 2);
                            Mips.add(sw);
                        }
                        /*String address1 = processPair(pAddr1, Mips);
                        CalRI sll1 = new CalRI(MIPS.Mips.Operate.SLL, address1, address1, "2", 1);
                        CalRI sw = new CalRI(MIPS.Mips.Operate.SW, right1, getAddrStr(left.getAddress()), address1, 2);
                        Mips.add(sll1);
                        Mips.add(sw);*/
                        freeMap(right1);
                        freeMap(address1);
                    } else {
                        String temp2 = findMap();
                        Pairs pAddr1 = containsIdent(assign.getAddress().getToken());
                        if (pAddr1 == null) {
                            pAddr1 = assign.getAddress();
                        } else if (isArray(pAddr1)) {
                            pAddr1 = containsIdent(assign.getAddress().getToken()).clone();
                            pAddr1.setParams(assign.getAddress().getParams());
                        }
                        Pairs pAddr2 = containsIdent(assign.getAddress2().getToken());
                        if (pAddr2 == null) {
                            pAddr2 = assign.getAddress2();
                        } else if (isArray(pAddr2)) {
                            pAddr2 = containsIdent(assign.getAddress2().getToken()).clone();
                            pAddr2.setParams(assign.getAddress2().getParams());
                        }
                        String address2 = processPair(pAddr2, Mips);
                        CalRI sll2 = new CalRI(MIPS.Mips.Operate.SLL, address2, address2, "2", 1);
                        Mips.add(sll2);
                        if (right.getIsParam()) {
                            //String temp3 = findMap();
                            if (right.getAddress() > 0) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp2, Integer.toString(right.getAddress()), "$sp", 2);
                                Mips.add(lw);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp2, temp2, address2, 1);
                                Mips.add(addu);
                            } else {
                                Binary li = new Binary(MIPS.Mips.Operate.LI, temp2, getAddrStr(right.getAddress()));
                                Mips.add(li);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp2,temp2,"$sp",1);
                                Mips.add(addu);
                                CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU, temp2, temp2, address2, 1);
                                Mips.add(subu);
                            }
                            CalRI lw2 = new CalRI(MIPS.Mips.Operate.LW, temp2, "0", temp2, 2);
                            //Mips.add(lw);
                            Mips.add(lw2);
                        } else {
                            CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp2, getAddrStr(right.getAddress()), address2, 2);
                            Mips.add(lw);
                        }
                        freeMap(address2);
                        String address1 = processPair(pAddr1, Mips);
                        CalRI sll1 = new CalRI(MIPS.Mips.Operate.SLL, address1, address1, "2", 1);
                        Mips.add(sll1);
                        if (left.getIsParam()) {
                            String temp3 = findMap();
                            if (left.getAddress() > 0) {
                                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp3, Integer.toString(left.getAddress()), "$sp", 2);
                                Mips.add(lw);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                                Mips.add(addu);
                            } else {
                                Binary li = new Binary(MIPS.Mips.Operate.LI, temp3, getAddrStr(left.getAddress()));
                                Mips.add(li);
                                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp3,temp3,"$sp",1);
                                Mips.add(addu);
                                CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU, temp3, temp3, address1, 1);
                                Mips.add(subu);
                            }
                            //CalRI lw2 = new CalRI(MIPS.Mips.Operate.LW,temp3,"0",temp3,2);
                            CalRI sw = new CalRI(MIPS.Mips.Operate.SW, temp2, "0", temp3, 2);
                            //Mips.add(lw);
                            Mips.add(sw);
                        } else {
                            CalRI sw = new CalRI(MIPS.Mips.Operate.SW, temp2, getAddrStr(left.getAddress()), address1, 2);
                            Mips.add(sw);
                        }
                        freeMap(temp2);
                        freeMap(address1);
                        //tables.peek().addPair(((Assign) IRs.get(i)).getPairs());
                    }
                }
                if (containsIdent(((Assign) IRs.get(i)).getPairs().getToken()) == null) {
                    tables.peek().addPair(((Assign) IRs.get(i)).getPairs());
                }
            }
        }
        return i;
    }

    public String processPair(Pairs pa, ArrayList<Mips> Mips) {
        String temp;
        //pa = containsIdent(pa.getToken()) == null ? pa : containsIdent(pa.getToken());
        if (pa.getKind().equals(Pairs.Kind.NUM) || containsIdent(pa.getToken()) == null) {
            temp = findMap();
            Binary li = new Binary(MIPS.Mips.Operate.LI, temp, Integer.toString(pa.getValue()));
            Mips.add(li);
        } else if (pa.getToken().contains("&")) {
            Pairs pairs = containsIdent(pa.getToken());
            if (pairs != null) {
                temp = pairs.getReg();
            } else {
                temp = transToReg(pa.getToken());
            }
        } else if (pa.getKind().equals(Pairs.Kind.ARRAY_VAL) || pa.getKind().equals(Pairs.Kind.ARRAY_VAR)) {
            temp = findMap();
            if (pa.getIsParam()) {
                String temp1 = findMap();
                Pairs pAddr1 = containsIdent(pa.getParams().get(0).getToken());
                if (pAddr1 == null) {
                    pAddr1 = pa.getParams().get(0);
                } else if (isArray(pa.getParams().get(0))) {
                    pAddr1 = containsIdent(pa.getParams().get(0).getToken()).clone();
                    pAddr1.setParams(pa.getParams().get(0).getParams());
                }
                String address = processPair(pAddr1, Mips);
                CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                Mips.add(sll);
                if (pa.getAddress() > 0) {
                    CalRI lwA = new CalRI(MIPS.Mips.Operate.LW, temp1, Integer.toString(pa.getAddress()), "$sp", 2);
                    Mips.add(lwA);
                    CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp1,temp1,address,1);
                    Mips.add(addu);
                } else {
                    Binary li = new Binary(MIPS.Mips.Operate.LI,temp1,getAddrStr(pa.getAddress()));
                    CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU,temp1,temp1,"$sp",1);
                    CalRI subu = new CalRI(MIPS.Mips.Operate.ADDU,temp1,temp1,address,1);
                    Mips.add(li);
                    Mips.add(addu);
                    Mips.add(subu);
                }
                //CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp1, temp1, address, 1);
                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, "0", temp1, 2);
                //Mips.add(addu);
                Mips.add(lw);
                freeMap(address);
                freeMap(temp1);
            } else {
                String temp1 = findMap();
                Pairs pAddr1 = containsIdent(pa.getParams().get(0).getToken());
                if (pAddr1 == null) {
                    pAddr1 = pa.getParams().get(0);
                } else if (isArray(pa.getParams().get(0))) {
                    pAddr1 = containsIdent(pa.getParams().get(0).getToken()).clone();
                    pAddr1.setParams(pa.getParams().get(0).getParams());
                }
                String address = processPair(pAddr1, Mips);
                CalRI sll = new CalRI(MIPS.Mips.Operate.SLL, address, address, "2", 1);
                //CalRI lwA = new CalRI(MIPS.Mips.Operate.LW,temp1,getAddrStr(pa.getAddress()),"$0",2);
                Binary li = new Binary(MIPS.Mips.Operate.LI, temp1, getAddrStr(pa.getAddress()));
                CalRI addu = new CalRI(MIPS.Mips.Operate.ADDU, temp1, temp1, address, 1);
                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, "0", temp1, 2);
                Mips.add(sll);
                Mips.add(li);
                Mips.add(addu);
                Mips.add(lw);
                freeMap(address);
                freeMap(temp1);
            }
        } else {
            temp = findMap();
            if (pa.getIsParam()) {
                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, Integer.toString(pa.getAddress()), "$sp", 2);
                Mips.add(lw);
            } else {
                CalRI lw = new CalRI(MIPS.Mips.Operate.LW, temp, getAddrStr(pa.getAddress()), "$0", 2);
                Mips.add(lw);
            }
        }
        return temp;
    }
}
